package com.mbbmap.app.form;

import java.util.*;
import java.text.*;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.*;
import org.apache.commons.lang.StringUtils;

import com.mbbmap.util.Constants;
import com.mbbmap.util.DateUtil;

/**
 * <code>CommonActionForm</code> is an abstract class that extends the
 * <code>org.apache.struts.action.ActionForm</code> class. It contains
 * implementation of common validation methods.
 * <p>
 * Subclasses of the <code>CommonActionForm</code> can use these validation
 * methods to validate the parameters in the form bean.
 *
 */
public abstract class CommonActionForm extends ActionForm {

	/**
	 * The form bean property that corresponds to the "dispatch" parameter used in
	 * <code>com.ebpp.m2u.cus.business.action.CommonDispatchAction</code>. Must match
	 * the value defined in <code>com.ebpp.m2u.cus.util.Constants.KEY_DISPATCH</code>.
	 */
	protected String dispatch;

	/**
	 * Setter for the dispatch field
	 */
	public void setDispatch(String dispatch) {
		this.dispatch = dispatch;
	}

	/**
	 * getter for the dispatch field
	 */
	public String getDispatch() {
		return this.dispatch;
	}

	public void reset(ActionMapping mapping, HttpServletRequest request) {
	}

    /**
     * Verifies that the field is not null or is an empty string or consists only of
     * whitespaces.
     *
     * @param field The field to verify
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyNotBlank(String field, String key, ActionErrors errors) {
		if (StringUtils.isBlank(field)) {
			errors.add(key, new ActionError("error.general.field.mandatory"));
		}

		return errors;
	}

    /**
     * Verifies that the field value has a length less than or equal to a specified limit.
     * No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param limit The maximum length allowed for this field
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyLength(String field, int limit, String key, ActionErrors errors) {
		if (StringUtils.isNotBlank(field)) {
			if (field.length() > limit) {
				errors.add(key, new ActionError("error.general.field.length.exceed", Integer.toString(limit)));
			}
		}

		return errors;
	}

    /**
     * Verifies that the field contains only numeric values (0...9)
     * No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsNumeric(String field, String key, ActionErrors errors) {
		if (StringUtils.isNotBlank(field)) {
			if (!StringUtils.isNumeric(field)) {
				errors.add(key, new ActionError("error.general.field.must.numeric"));
			}
		}

		return errors;
	}

    /**
     * Verifies that the field contains either a number with decimal point or an integer.
     * No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsDecimalOrInteger(String field, String key, ActionErrors errors) {
		if (StringUtils.isNotBlank(field)) {
			if (StringUtils.contains(field, '.')) {
				String tmpField[] = StringUtils.split(field, '.');

				if (tmpField.length != 2) {
					errors.add(key, new ActionError("error.general.field.must.numeric"));
				} else {
					if (tmpField[1].length() != 2) {
						errors.add(key, new ActionError("error.general.field.must.numeric"));
					} else {
						if (!StringUtils.isNumeric(tmpField[0])) {
							errors.add(key, new ActionError("error.general.field.must.numeric"));
						} else {
							if (!StringUtils.isNumeric(tmpField[1])) {
								errors.add(key, new ActionError("error.general.field.must.numeric"));
							}
						}
					}
				}

			} else {
				if (!StringUtils.isNumeric(field)) {
					errors.add(key, new ActionError("error.general.field.must.numeric"));
				}
			}
		}

		return errors;
	}

    /**
     * Verifies that the field contains only numeric values (0...9), alphabets (a...z, A...Z) or
     * spaces. No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsAlphanumericOnly(String field, String key, ActionErrors errors) {
		if (StringUtils.isNotBlank(field)) {
			if (!StringUtils.isAlphanumericSpace(field)) {
				errors.add(key, new ActionError("error.general.field.must.alphanumeric"));
			}
		}

		return errors;
	}

    /**
     * Verifies that the field contains only numeric values (0...9), alphabets (a...z, A...Z),
     * spaces or the search wildcard character (%). No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsAlphanumericOrSearch(String field, String key, ActionErrors errors) {
		if (StringUtils.isNotBlank(field)) {
			String tmpField = StringUtils.replaceChars(field, '%', ' ');
			if (!StringUtils.isAlphanumericSpace(tmpField)) {
				errors.add(key, new ActionError("error.general.field.must.alphanumeric.or.search", "%"));
			}
		}

		return errors;
	}


    /**
     * Verifies that the field value is an integer and it is between the specified
     * lower limit and upper limit (inclusive).
     * <p>
     * No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param lowerLimit The lower limit of the allowed range
     * @param upperLimit The upper limit of the allowed range
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsWithinLimitInclusive(String field, int lowerLimit, int upperLimit,
		String key, ActionErrors errors) {

		if (StringUtils.isNotBlank(field)) {
			if (!StringUtils.isNumeric(field)) {
				errors.add(key, new ActionError("error.general.field.must.numeric"));
			} else {
				int val = Integer.parseInt(field);
				if ((val > upperLimit) || (val < lowerLimit)) {
					errors.add(key, new ActionError("error.general.field.limit.inclusive", Integer.toString(lowerLimit), Integer.toString(upperLimit)));
				}
			}
		}

		return errors;

	}

    /**
     * Verifies that the field value is an integer and it is between the specified
     * lower limit and upper limit (exclusive).
     * <p>
     * No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param lowerLimit The lower limit of the allowed range
     * @param upperLimit The upper limit of the allowed range
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsWithinLimitExclusive(String field, int lowerLimit, int upperLimit,
		String key, ActionErrors errors) {

		if (StringUtils.isNotBlank(field)) {
			if (!StringUtils.isNumeric(field)) {
				errors.add(key, new ActionError("error.general.field.must.numeric"));
			} else {
				int val = Integer.parseInt(field);
				if ((val >= upperLimit) || (val <= lowerLimit)) {
					errors.add(key, new ActionError("error.general.field.limit.exclusive", Integer.toString(lowerLimit), Integer.toString(upperLimit)));
				}
			}
		}

		return errors;

	}

    /**
     * Verifies that the field value is an integer and it is greater than or equal to zero.
     * <p>
     * No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsGreaterThanOrEqualToZero(String field, String key, ActionErrors errors) {

		if (StringUtils.isNotBlank(field)) {
			if (!StringUtils.isNumeric(field)) {
				errors.add(key, new ActionError("error.general.field.must.numeric"));
			} else {
				int val = Integer.parseInt(field);
				if (val < 0) {
					errors.add(key, new ActionError("error.general.field.must.zero.or.greater"));
				}
			}
		}

		return errors;
	}

    /**
     * Verifies that the field value is an integer and it is greater than zero.
     * <p>
     * No error is returned if the field is blank.
     *
     * @param field The field to verify
     * @param key The <code>ActionError</code> key for this field
     * @param errors The <code>ActionErrors</code> object that will updated (if necessary)
     *
     * @return The <code>ActionErrors</code> that contains the appropriate error message (if any)
     *
     */
	protected ActionErrors verifyIsGreaterThanZero(String field, String key, ActionErrors errors) {

		if (StringUtils.isNotBlank(field)) {
			if (!StringUtils.isNumeric(field)) {
				errors.add(key, new ActionError("error.general.field.must.numeric"));
			} else {
				int val = Integer.parseInt(field);
				if (val <= 0) {
					errors.add(key, new ActionError("error.general.field.must.greater.than.zero"));
				}
			}
		}

		return errors;
	}


	protected ActionErrors verifyOptionSelected(String field, String key, ActionErrors errors) {
		if (field.equals(Constants.NO_OPTION_SELECTED)) {
			errors.add(key, new ActionError("error.general.field.mandatory"));
		}

		return errors;
	}

	protected ActionErrors verifyFromMonthLessThanOrEqualToToMonth(
		String fromStmtMonth, String toStmtMonth,
		String key, ActionErrors errors) {
		try {
	  	  Date date1 = DateUtil.createDateUniversal(fromStmtMonth);
	  	  Date date2 = DateUtil.createDateUniversal(toStmtMonth);

			if (date1.after(date2)) {
				errors.add(key, new ActionError("error.general.field.from.month.greater.than.to.month"));
			}
		} catch (ParseException e) {
			System.out.println(e.toString());
			e.printStackTrace();
		}
		return errors;
	}

}